package com.glsc.ngateway.opmanage.service.other;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.glsc.ngateway.common.api.common.enums.Constant;
import com.glsc.ngateway.common.api.common.enums.DictConstant;
import com.glsc.ngateway.common.base.repo.mysql.gateway.other.TradeSeatHistoryRepository;
import com.glsc.ngateway.common.api.common.utils.CommonUtils;
import com.glsc.ngateway.common.api.common.ex.GatewayException;
import com.glsc.ngateway.opmanage.aspect.UserCache;
import com.glsc.ngateway.opmanage.event.vo.TradeSeatApplicationEvent;
import com.glsc.ngateway.opmanage.utils.RequestTool;
import com.glsc.ngateway.opmanage.utils.SpecificationUtil;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.TradeSeatHistory;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.TradeSeatRent;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.User;
import com.glsc.ngateway.common.base.domainmapper.TradeSeatRentMapper;
import com.glsc.ngateway.common.api.platform.dto.other.TradeSeatRentDto;
import com.glsc.ngateway.common.base.repo.mysql.gateway.other.TradeSeatRentRepository;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author zzp
 * @date 2022/6/6
 * 交易单元租用信息表
 */
@Service
public class TradeSeatRentService {

    private static final Logger logger = LoggerFactory.getLogger(TradeSeatRentService.class);

    @Resource
    private TradeSeatRentRepository tradeSeatRentRepository;
    @Resource
    private TradeSeatHistoryRepository tradeSeatHistoryRepository;
    @Autowired
    private UserCache userCache;

    @Autowired
    private RequestTool requestTool;

    @Resource
    private ApplicationContext applicationContext;


    /**
     * 保存或更新交易单元租用信息
     * 如果 交易单元+市场，已经存在则更新记录
     *
     * @param tradeSeatRentDto
     */
    public TradeSeatRentDto saveOrUpdate(TradeSeatRentDto tradeSeatRentDto) {
        logger.info("创建交易单元租用流水信息，入参TradeSeatRentDto：" + tradeSeatRentDto);
        //校验数据
        if (null == tradeSeatRentDto) {
            throw GatewayException.error("创建信息无效");
        }
        TradeSeatRent tradeSeatRent = getTradeSeatRentByCodeAndMarket(tradeSeatRentDto.getTradeSeatCode(), tradeSeatRentDto.getTradeSeatMarket());
        if (tradeSeatRent == null) {
            tradeSeatRent = TradeSeatRentMapper.INSTANCE.dto2domain(tradeSeatRentDto);
        } else {
            logger.info("交易单元{}-{}，已经存在，则尝试更新，对应rentId={}", tradeSeatRentDto.getTradeSeatCode()
                    , tradeSeatRentDto.getTradeSeatMarket(), tradeSeatRent.getTradeSeatRentId());
            tradeSeatRentDto.setTradeSeatRentId(tradeSeatRent.getTradeSeatRentId());
            applicationContext.publishEvent(TradeSeatApplicationEvent.convert(tradeSeatRent.getState(), tradeSeatRentDto.getState(),
                    tradeSeatRent.getTradeSeatCode(), tradeSeatRent.getBeginDate(), tradeSeatRent.getEndDate(), tradeSeatRentDto.getBeginDate()));
            tradeSeatRent = TradeSeatRentMapper.INSTANCE.dto2domain(tradeSeatRentDto);
        }

        User createUser = userCache.get(requestTool.getAccountFromRequest());
        tradeSeatRent.setCreateOperator(createUser.getUsername());
        tradeSeatRent.setCreateOperatorName(createUser.getName());
//        tradeSeatRent.setState(DictConstant.TRADE_SEAT_STATE_BEGIN);
//        tradeSeatRent.setDataSource(DictConstant.TRADE_SEAT_SOURCE_MANU);
//        RequestTool.fillOpInfo(tradeSeatRent, DictConstant.OP_SOURCE_WEB, DictConstant.OP_ACTION_ADD);
        TradeSeatRent TradeSeatRentSaved = tradeSeatRentRepository.save(tradeSeatRent);

        return TradeSeatRentMapper.INSTANCE.domain2dto(TradeSeatRentSaved);
    }

    /**
     * 保存或更新交易单元租用信息
     * 数据来源于租用流水表
     *
     * @param tradeSeatHistory
     */
    public TradeSeatRentDto saveOrUpdateFromRentHistory(TradeSeatHistory tradeSeatHistory) {
        logger.info("创建交易单元租用流水信息，入参TradeSeatRentDto：" + tradeSeatHistory);
        //校验数据
        if (null == tradeSeatHistory) {
            throw GatewayException.error("创建信息无效：" + tradeSeatHistory);
        }
        logger.info("交易单元信息查询记录record{}-{}，不存在", tradeSeatHistory.getTradeSeatCode()
                , tradeSeatHistory.getTradeSeatMarket());
        TradeSeatRent tradeSeatRent = getTradeSeatRentByCodeAndMarket(tradeSeatHistory.getTradeSeatCode(), tradeSeatHistory.getTradeSeatMarket());
        if (tradeSeatRent == null) {
            tradeSeatRent = new TradeSeatRent();
            if (StrUtil.isEmpty(tradeSeatHistory.getTradeSeatCode()) || StrUtil.isEmpty(tradeSeatHistory.getTradeSeatMarket())) {
                if (tradeSeatHistory.getChangeTypeCode() != null && tradeSeatHistory.getChangeTypeCode() == 1) {
                    logger.info("交易单元LOF/ETF变更没有seatcode{}-{}，不需要处理", tradeSeatHistory.getTradeSeatCode()
                            , tradeSeatHistory.getTradeSeatMarket());
                    return null;
                }
                logger.info("交易单元{}-{}，不存在", tradeSeatHistory.getTradeSeatCode()
                        , tradeSeatHistory.getTradeSeatMarket());
                throw new IllegalArgumentException("交易单元或交易市场为空");
            }
            logger.info("交易单元{}-{}，不存在，则尝试新增", tradeSeatHistory.getTradeSeatCode()
                    , tradeSeatHistory.getTradeSeatMarket());
            CommonUtils.copyPropertiesIgnoreNullOrEmptyString(tradeSeatHistory, tradeSeatRent);
        } else {
            logger.info("交易单元{}-{}，已经存在，则尝试更新，对应rentId={}", tradeSeatHistory.getTradeSeatCode()
                    , tradeSeatHistory.getTradeSeatMarket(), tradeSeatRent.getTradeSeatRentId());

            //【重要】仅更新不为空的字段信息
            CommonUtils.copyPropertiesIgnoreNullOrEmptyString(tradeSeatHistory, tradeSeatRent);
        }

        User createUser = userCache.get(CommonUtils.getString(requestTool.getAccountFromRequest(), Constant.USER_ADMIN));
        if (createUser != null) {
            tradeSeatRent.setCreateOperator(createUser.getUsername());
            tradeSeatRent.setCreateOperatorName(createUser.getName());
        } else {
            tradeSeatRent.setCreateOperator("admin");
            tradeSeatRent.setCreateOperatorName("管理员");
        }

//        tradeSeatRent.setState(DictConstant.TRADE_SEAT_STATE_BEGIN);
//        tradeSeatRent.setDataSource(DictConstant.TRADE_SEAT_SOURCE_MANU);
//        RequestTool.fillOpInfo(tradeSeatRent, DictConstant.OP_SOURCE_WEB, DictConstant.OP_ACTION_ADD);

        TradeSeatRent TradeSeatRentSaved = tradeSeatRentRepository.save(tradeSeatRent);

        logger.info("保存交易单元信息：", tradeSeatRent);

        return TradeSeatRentMapper.INSTANCE.domain2dto(TradeSeatRentSaved);
    }

    /**
     * 批量创建交易单元信息
     */
    public void saveTradeSeatRentList(List<TradeSeatRent> tradeSeatRentList) {
        if (CollectionUtil.isEmpty(tradeSeatRentList)) {
            return;
        }

        for (TradeSeatRent tradeSeatRent : tradeSeatRentList) {
//            RequestTool.fillOpInfo(tradeSeatRent, DictConstant.OP_SOURCE_WEB, DictConstant.OP_ACTION_ADD);
            TradeSeatRent tradeSeatRentDB = getTradeSeatRentByCodeAndMarket(tradeSeatRent.getTradeSeatCode(), tradeSeatRent.getTradeSeatMarket());
            if (tradeSeatRentDB != null) {
                logger.info("交易单元{}-{}，已经存在，则尝试更新，对应rentId={}", tradeSeatRentDB.getTradeSeatCode()
                        , tradeSeatRentDB.getTradeSeatMarket(), tradeSeatRent.getTradeSeatRentId());
                tradeSeatRent.setTradeSeatRentId(tradeSeatRentDB.getTradeSeatRentId());//已经存在，则更新（填写主键）
                tradeSeatRent.setOpAction(DictConstant.OP_ACTION_UPDATE);
            }
        }
        tradeSeatRentRepository.saveAll(tradeSeatRentList);
    }

    /**
     * 根据TradeSeatId设置为停用标记
     *
     * @return
     */
    @Transactional
    public TradeSeatRentDto updateStateEndByTradeSeatId(Integer tradeSeatId) {
        logger.info("停用交易单元租用流水信息，入参tradeSeatId：" + tradeSeatId);
        if (tradeSeatId == null || tradeSeatId <= 0) {
            throw GatewayException.error("TradeSeatId:" + tradeSeatId + "，不合法");
        }

        TradeSeatRent TradeSeatRentDB = getTradeSeatRentByTradeSeatId(tradeSeatId);

        if (TradeSeatRentDB == null) {
            throw GatewayException.error("TradeSeatId：" + tradeSeatId + "对应交易单元租用流水信息不存在不允许删除");
        }

        if (null != TradeSeatRentDB && DictConstant.TRADE_SEAT_STATE_BEGIN.equals(TradeSeatRentDB.getState())) {
            //设置停用状态
            TradeSeatRentDB.setState(DictConstant.TRADE_SEAT_STATE_END);
//            RequestTool.fillOpInfo(TradeSeatRentDB, DictConstant.OP_SOURCE_WEB, DictConstant.OP_ACTION_DELETE);

            TradeSeatRent TradeSeatRentSaved = tradeSeatRentRepository.save(TradeSeatRentDB);
            return TradeSeatRentMapper.INSTANCE.domain2dto(TradeSeatRentSaved);
        } else {
            return null;
        }
    }

    /**
     * 分页条件查询
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Page<TradeSeatRentDto> findPage(String tradeSeatCode, String tradeSeatMarket, String applyDeptName, String useType, String useCompanyName, int pageNo, int pageSize) {
        logger.info("分页条件查询交易单元租用信息");
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "tradeSeatRentId";

        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);

        Map<String, Object> param = new HashMap<>();
        if (StrUtil.isNotEmpty(tradeSeatCode)) {
            param.put("LIKE_tradeSeatCode", tradeSeatCode);
        }
        if (StrUtil.isNotEmpty(tradeSeatMarket)) {
            param.put("EQ_tradeSeatMarket", tradeSeatMarket);
        }
        if (StrUtil.isNotEmpty(applyDeptName)) {
            param.put("LIKE_applyDeptName", applyDeptName);
        }
        if (StrUtil.isNotEmpty(useType)) {
            param.put("EQ_useType", useType);
        }
        if (StrUtil.isNotEmpty(useCompanyName)) {
            param.put("LIKE_useCompanyName", useCompanyName);
        }

        Page<TradeSeatRent> ret = tradeSeatRentRepository.findAll(SpecificationUtil.buildSpecification(param, TradeSeatRent.class), pageable);
        return domainToDto(ret, pageable);
    }

    /**
     * domain转Dto
     *
     * @param ret
     * @param pageable
     * @return
     */
    private Page<TradeSeatRentDto> domainToDto(Page<TradeSeatRent> ret, Pageable pageable) {
        Page<TradeSeatRentDto> page;
        //domain转成dto
        if (null != ret && ret.getNumberOfElements() > 0) {
            List<TradeSeatRentDto> contentList = TradeSeatRentMapper.INSTANCE.domain2dto(ret.getContent());
            page = new PageImpl(contentList, pageable, ret.getTotalElements());
        } else {
            page = new PageImpl(new ArrayList(), pageable, ret.getTotalElements());
        }
        return page;
    }

    /**
     * 根据条件查询List
     */
    public List<TradeSeatRent> findList(Map<String, Object> param) {
        return tradeSeatRentRepository.findAll(SpecificationUtil.buildSpecification(param, TradeSeatRent.class));
    }

    /**
     * 根据条件查询List
     * @param tradeSeatRent
     * @return
     */
    public List<TradeSeatRent> findList(TradeSeatRent tradeSeatRent) {
        if (Objects.isNull(tradeSeatRent)) {
            return null;
        }
        return tradeSeatRentRepository.findAll(Example.of(tradeSeatRent));
    }

    /*
     * 根据租用信息ID查询
     * */
    private TradeSeatRent getTradeSeatRentByTradeSeatId(Integer tradeSeatId) {
        return tradeSeatRentRepository.findByTradeSeatRentId(tradeSeatId);
    }

    /*
     * 根据交易单元号+市场，唯一key，检索交易单元租用信息
     * */
    private TradeSeatRent getTradeSeatRentByCodeAndMarket(String tradeSeatCode, String tradeSeatMarket) {
        return tradeSeatRentRepository.findByTradeSeatCodeAndTradeSeatMarket(tradeSeatCode, tradeSeatMarket);
    }

    /*
     * 根据交易单元号+市场，唯一key，检索交易单元租用信息
     * */
    public TradeSeatRent getTradeSeatRentByCode(String tradeSeatCode) {
        return tradeSeatRentRepository.findByTradeSeatCode(tradeSeatCode);
    }

    /**
     * 通过交易单元流水更新台账信息
     *
     * @return
     */
    @XxlJob("tradeSeatRentService_updateTradeSeatRentByHistory")
    public String updateTradeSeatRentByHistory() {
        List<TradeSeatHistory> hisList = tradeSeatHistoryRepository.findAll();
        hisList.forEach(
                e -> this.saveOrUpdateFromRentHistory(e)
        );
        return "success";
    }
}
